#include "StdAfx.h"

WMOGroup::WMOGroup(std::string szBaseName, ui32 numGroup, WMOModel* pParnet) : m_pParent(pParnet)
{
	mIsLoaded = false;
	m_meshes = NULL;
	size_t pos = szBaseName.rfind('.');
	szBaseName = szBaseName.substr(0, pos);
	char wmopath[255];
	sprintf_s(wmopath, "%s_%03d.wmo", szBaseName.c_str(), numGroup);
	m_szFileName = wmopath;
	m_file = new CMpqFile(wmopath);
	if(!m_file->IsOpened())
		m_file = 0;
}

bool WMOGroup::Init()
{
	if(!m_file)
		return false;

	ui32 sig = 0, len = 0;
	while(LoadChunk(sig, len))
	{
		switch(sig)
		{
		case 0x4D4F5649:
			{
				m_indices = (MOVI*)m_file->GetCurPointer();
				m_file->ModInc(len);
				break;
			}

		case 0x4D4F5654:
			{
				m_vertices = (Vertex3F*)m_file->GetCurPointer();
				m_file->ModInc(len);
				break;
			}
			
		case 0x4D4F4241:
			{
				LoadBatches();
				break;
			}

		case 0x4D4F4750:
			{
				m_file->ReadInc(sizeof(MOGP), &m_header);
				break;
			}

		case 0x4D4F5456:
			{
				m_texcoords = (Vertex2F*)m_file->GetCurPointer();
				m_file->ModInc(len);
				break;
			}

		default:
			m_file->ModInc(len);
			break;
		}
	}
	return true;
}

ui32 WMOGroup::LoadChunk(ui32& sig, ui32& len)
{
	if(!m_file)
		return ui32(-1);
	sig = 0;
	m_file->ReadInc(4, &sig);
	if(sig == 0)
		return 0;
	m_file->ReadInc(4, &len);
	if(len == 0)
		return 1;
	if(m_file->TellInc() + len > m_file->GetSize())
		return 0;
	return 1;
}

void WMOGroup::LoadBatches()
{
	MOBA mob;
	m_meshes = new Mesh*[m_header.numBatchesA + m_header.numBatchesB + m_header.numBatchesC];
	m_textures = new Texture*[m_header.numBatchesA + m_header.numBatchesB + m_header.numBatchesC];
	for(ui32 i = 0; i < (m_header.numBatchesA + m_header.numBatchesB + m_header.numBatchesC); ++i)
	{
		m_file->ReadInc(sizeof(mob), &mob);
		mBatches.push_back(mob);
	}
}

bool WMOGroup::execute() {
	for(ui32 i = 0; i < (m_header.numBatchesA + m_header.numBatchesB + m_header.numBatchesC); ++i) {
		MOBA mob = mBatches[i];
		Vertex3FT* tmp = new Vertex3FT[mob.numIndices];
		for(ui32 t = 0, j = mob.startIndex; t < mob.numIndices; ++t, ++j)
		{
			ui32 subindex = (ui32)floor((float)j / 3);
			ui32 ofs = j % 3;
			ui32 index = 0;
			MOVI& movi = m_indices[subindex];
			switch(ofs)
			{
			case 0:
				index = movi.p1;
				break;
			case 1:
				index = movi.p2;
				break;
			case 2:
				index = movi.p3;
				break;
			}
			tmp[t].x = m_vertices[index].x;
			tmp[t].y = m_vertices[index].z;
			tmp[t].z = m_vertices[index].y;
			tmp[t].u = m_texcoords[index].x;
			tmp[t].v = m_texcoords[index].y;
		}
		m_meshes[i] = new Mesh();
		m_meshes[i]->Load(tmp, VERTEX3FT, mob.numIndices, mob.numIndices / 3);
		m_textures[i] = m_pParent->GetTexture(mob.textureId);
		delete [] tmp;
	}

	mIsLoaded = true;
	return true;
}